﻿using DotNet.Utilities.ConsoleHelper;
using PropertyChanged;
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using DotNet.Utilities;
using WPFPractice.Models;
using WPFPractice.Utils;
using WPFTemplateLib.WpfHelpers;
using System.Windows.Controls;

namespace WPFPractice.Windows
{
    public partial class WinDataGrid : Window
    {
        private DataGridViewModel _vm;

        public WinDataGrid()
        {
            InitializeComponent();
            DataContext = _vm = new DataGridViewModel();
        }

        #region 误触问题演示

        private void EventSetter_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            //真实触摸时会触发 PreviewTouchDown 事件，而误触时（点击弹窗取消后在空白处点击多次会误触表格）则不会（因为那个只触发是鼠标事件）;
            _vm.IsRealTouch = true;
        }

        /* 注意：触摸事件之后还会触发鼠标事件 */

        private void EventSetter_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            //StylusDevice属性，触屏操作连带触发时不为null，鼠标触发时为null
            if (e.StylusDevice != null)
            {//触屏
                //e.Handled = true;
            }
            else
            {//鼠标
                _vm.IsRealTouch = true; //避免后续判断不正常;
            }
        }

        /*模式弹窗会阻止后续的事件，比如在 SelectionChanged 中弹窗，会阻止之后的 Up 事件*/

        private void EventSetter_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            _vm.IsRealTouch = true;
        }

        #endregion

        private void EventSetter_LostFocus(object sender, RoutedEventArgs e)
        {
            var selected = _vm.SelectedUser;
            if(selected != null)
            {
                //selected.EditType = EditTypeEnum.Show;
            }
        }
    }

    [AddINotifyPropertyChangedInterface]
    public class DataGridViewModel : MyBindableBase
    {
        #region 成员

        /// <summary>
        /// 是否是真实触控（用于解决表格误触问题）
        /// </summary>
        public bool IsRealTouch { get; set; }

        /// <summary>
        /// 改变前的对象引用
        /// </summary>
        private User _originUser;

        #endregion

        #region Bindable

        /// <summary>
        /// 表格数据
        /// </summary>
        public ObservableCollection<User> Datas { get; set; }

        /// <summary>
        /// 选中项
        /// </summary>
        public User SelectedUser { get; set; }

        private EditTypeEnum _editType = EditTypeEnum.Show;
        /// <summary>
        /// 编辑模式
        /// </summary>
        public EditTypeEnum EditType
        {
            get => _editType;
            set
            {
                _editType = value;
                ShowInfo($"切换到 {_editType.GetEnumDescription()}");
            }
        }

        /// <summary>
        /// 是否显示个性签名
        /// </summary>
        public bool IsShowSignature { get; set; } = true;

        #endregion

        #region Command

        /// <summary>
        /// 切换到新增模式命令
        /// </summary>
        public ICommand AddNewCmd { get; set; }

        /// <summary>
        /// 添加用户命令
        /// </summary>
        public ICommand AddUserCmd { get; set; }

        /// <summary>
        /// 表格选择行变化事件触发命令
        /// </summary>
        public ICommand SelectionChangedCmd { get; set; }

        /// <summary>
        /// 是否能执行选择行变化命令
        /// </summary>
        public bool IsCanSelectionChanged { get; set; } = true;

        /// <summary>
        /// 删除命令
        /// </summary>
        public ICommand DeleteCmd { get; set; }

        /// <summary>
        /// 显示隐藏个性签名命令
        /// </summary>
        public ICommand ShowOrHideSignCmd { get; set; }

        /// <summary>
        /// 进入编辑模式命令
        /// </summary>
        public ICommand EnterEditCmd { get; set; }

        /// <summary>
        /// 失去焦点事件命令
        /// </summary>
        public ICommand LostFocusCmd { get; set; }

        #endregion

        public DataGridViewModel()
        {
            SetCommandMethod();

            InitValue();

            Console.SetOut(new ConsoleWriter(s =>
            {
                ShowInfo(s);
            }));
        }

        /// <summary>
        /// 数据初始化
        /// </summary>
        private void InitValue()
        {
            ShowInfo("演示 DataGrid 自定义表头、误触问题");
            Datas = new ObservableCollection<User>()
            {
                new User(){UserId = "1111", UserName = "张三", Gender = "男", Age = 20, MobileNum = "13597362875", Address = "浙江省杭州市西湖区古墩路", Signature = "好好学习，天天向上"},
                new User(){UserId = "2222", UserName = "李四", Gender = "男", Age = 22, MobileNum = "13385937628", Address = "福建省南平市邵武市水北镇", Signature = "生命不息，奋斗不止"},
                new User(){UserId = "3333", UserName = "王妩", Gender = "女", Age = 24, MobileNum = "17129463982", Address = "美利坚共和国加利福尼亚洲", Signature = "天妒英才，命运多舛"},
                new User(){UserId = "4444", UserName = "赵溜", Gender = "男", Age = 28, MobileNum = "18868839476", Address = "火星基地一号华中区杭州堡", Signature = "人生一世，草木一秋"},
            };
        }

        /// <summary>
        /// 命令方法赋值(在构造函数中调用)
        /// </summary>
        private void SetCommandMethod()
        {
            AddNewCmd ??= new RelayCommand(o => true, o =>
            {
                EditType = EditTypeEnum.Add;
                SelectedUser = new User();
            });

            AddUserCmd ??= new RelayCommand(o => !(string.IsNullOrEmpty(SelectedUser?.UserId) || string.IsNullOrEmpty(SelectedUser?.UserName)), o =>
            {
                Datas.Add(SelectedUser);
                ShowInfo($"已添加用户 {SelectedUser.UserId}");

                EditType = EditTypeEnum.Show;
            });

            SelectionChangedCmd ??= new RelayCommand(o => IsCanSelectionChanged, o =>
            {
                try
                {
                    IsCanSelectionChanged = false;

                    var args = o as SelectionChangedEventArgs;
                    EditType = EditTypeEnum.Show;

                    var isOk = MessageBox.Show($"是否切换？（是否是误触？{!IsRealTouch}）", "触屏误触问题演示", MessageBoxButton.YesNo);
                    if (isOk == MessageBoxResult.No)
                    {
                        if (SelectedUser != _originUser)
                        {
                            SelectedUser = _originUser;
                        }

                        return;
                    }

                    if (_originUser != null)
                    {
                        _originUser.EditType = EditTypeEnum.Show;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                finally
                {
                    IsRealTouch = false;
                    _originUser = SelectedUser;

                    IsCanSelectionChanged = true;
                }
            });

            DeleteCmd ??= new RelayCommand(o => true, o =>
            {
                var user = o as User;
                if(user == null)
                {
                    return;
                }

                Datas.Remove(user);
                ShowInfo($"已删除用户[{user.UserId}]");
                EditType = EditTypeEnum.Show;
            });

            ShowOrHideSignCmd ??= new RelayCommand(o => true, o =>
            {
                IsShowSignature = !IsShowSignature;
            });

            EnterEditCmd ??= new RelayCommand(o => true, o =>
            {
                EditType = EditTypeEnum.Edit;
                if (SelectedUser != null)
                {
                    SelectedUser.EditType = EditType;
                }
            });

            LostFocusCmd ??= new RelayCommand(o => true, o =>
            {
                var args = o as RoutedEventArgs;

                if (args.Source.GetType() == typeof(DataGrid) && SelectedUser != null)
                {
                    //SelectedUser.EditType = EditTypeEnum.Show;
                }
            });
        }
    }
}
